﻿using System;
using System.Collections.Generic;
using Papa.Common;

namespace InsuranceAdjuster.Helpers {
    /*
Character #1, length 3 of the VIN number is the World Manufacturer Identifier (WMI) the first character is the country, the next 1 or 2 designates the manufacturer. (see table below)
Character #4, length 5 of the VIN number is the body style or features, which varies by manufacturer
Character #9, length 1 of the VIN number is a check digit, which helps programs verify that the VIN has been entered accurately
Character #10, length 1 of the VIN number is the model year (see table below)
Character #11, length 1 of the VIN number identifies the assembly plant
Character #12, length 6 of the VIN number is the manufacturer sequence number

     */
    public class VINParser : NotifiableObject {
        private static Dictionary<string, string> manufacturerMap = null;
        private static Dictionary<string, string> modelMap = null;

        public static VinCarInfo Parse(string vin) {
            if (String.IsNullOrEmpty(vin))
                return new VinCarInfo(); ;
            return new VinCarInfo(GetYear(vin), GetMake(vin), GetModel(vin));
        }


        private static int? GetYear(string vin) {
            vin = vin.Trim().ToUpper();
            if (vin.Length < 10)
                return null;

            char i = 'I';
            char o = 'O';
            char q = 'Q';
            char u = 'U';

            int c = (int)vin.ToUpper()[9];
            if (c >= 65 && c <= 89) {
                int year = 1980 + c - 65;
                if (c > (int)i && c < (int)o)
                    year--;
                else if (c > (int)o && c < (int)q)
                    year -= 2;
                else if (c > (int)q && c < (int)u)
                    year -= 3;
                else if (c > (int)u)
                    year -= 4;
                return year;
            } else if (c >= 49 && c <= 57)
                return 2001 + c - 49;
            else
                return null;
        }

        private static string GetMake(string vin) {
            vin = vin.Trim().ToUpper();
            if (vin.Length < 2)
                return String.Empty;

            if (ManufacturerMap.ContainsKey(vin[1].ToString()))
                return ManufacturerMap[vin[1].ToString()];

            return String.Empty;
        }

        private static string GetModel(string vin) {
            vin = vin.Trim().ToUpper();
            if (vin.Length < 7)
                return String.Empty;

            if(ModelMap.ContainsKey(vin.Substring(3, 4)))
                return ModelMap[vin.Substring(3, 4)];

            return String.Empty;
        }

        private static Dictionary<string, string> ManufacturerMap {
            get {
                if (manufacturerMap != null)
                    return manufacturerMap;

                manufacturerMap = new Dictionary<string, string>();
                manufacturerMap.Add("B", "BMW");
                manufacturerMap.Add("4", "Buick");
                manufacturerMap.Add("6", "Cadillac");
                manufacturerMap.Add("1", "Chevrolet");
                manufacturerMap.Add("C", "Chrysler");
                manufacturerMap.Add("F", "Ford");
                manufacturerMap.Add("7", "GM Canada");
                manufacturerMap.Add("G", "General Motors");
                manufacturerMap.Add("H", "Honda");
                manufacturerMap.Add("A", "Jaguar");
                manufacturerMap.Add("L", "Lincoln");
                manufacturerMap.Add("D", "Mercedes Benz");
                manufacturerMap.Add("M", "Mercury");
                manufacturerMap.Add("N", "Nissan");
                manufacturerMap.Add("3", "Oldsmobile");
                manufacturerMap.Add("P", "Plymouth");
                manufacturerMap.Add("8", "Saturn");
                manufacturerMap.Add("T", "Toyota");
                manufacturerMap.Add("V", "Volvo");
                return manufacturerMap;
            }
        }

        private static Dictionary<string, string> ModelMap
        {
            get
            {
                if (modelMap != null)
                    return modelMap;

                modelMap = new Dictionary<string, string>();
                modelMap.Add("FF33", "7 series");
                modelMap.Add("HC13", "5 Series");
                modelMap.Add("AK03", "M3");
                modelMap.Add("CD52", "DeVille");
                modelMap.Add("EL52", "Eldorado");
                modelMap.Add("CB52", "Fleetwood");
                modelMap.Add("KS52", "Seville");
                modelMap.Add("5656", "Versa Hatchback");
                return modelMap;
            }
        }
    }
}
